﻿using System;
using System.Collections.Generic;
using System.Windows;

namespace jSLCore.Client.Presentation.BaseControl
{
    /// <summary>
    /// Базовый класс для всех диалогов
    /// </summary>
    public partial class DialogControl : DataControl , IDialogControl
    {
        #region ShowDialog
        
        public void ShowDialog( BaseControl parent)
        {
            ShowDialog(null, null, null, true, parent);
        }

        /// <summary>
        /// Показать диалоговое окно, с возможностью отмены и множественным выбором
        /// </summary>
        /// <param name="dialogControl">Диалог, который необходимо показать</param>
        /// <param name="multiDataSelectedEventHandler">Действие, на случай успешного диалога и возврата списка данных</param>
        public void ShowDialog(MultiDataSelectedEventHandler multiDataSelectedEventHandler, BaseControl parent)
        {
            ShowDialog(null, multiDataSelectedEventHandler, null, true,parent);
        }

        /// <summary>
        /// Показать диалоговое окно с возможностью отмены и единичным результатом
        /// </summary>
        /// <param name="dialogControl">Диалог, который необходимо показать</param>
        /// <param name="dataSelectedEventHandler">Действие на случай успешного диалога и возврата результата</param>
        public void ShowDialog(DataSelectedEventHandler dataSelectedEventHandler, BaseControl parent)
        {
            ShowDialog(dataSelectedEventHandler, null, null, true,parent);
        }

        


        public void ShowDialog(DataSelectedEventHandler dataSelectedEventHandler
            , MultiDataSelectedEventHandler multiDataSelectedEventHandler
            , EventHandler cancelHandler
            , bool allowCancel, BaseControl parent)
        {
            ApplicationContainer.ApplicationContainer appContainer;

#if SILVERLIGHT
            if(parent==null)
            {
                appContainer = ApplicationContainer.ApplicationContainer.Current;
            }
            else
            {
                appContainer = parent.ParentApplicationContainer;
            }
#else
            appContainer = parent.ParentApplicationContainer;
#endif


            if (appContainer==null)throw new InvalidOperationException("Provided parent BaseControl does not belong to any ApplicationContainer. Show parent control first");

            appContainer.ShowDialog(this, dataSelectedEventHandler, multiDataSelectedEventHandler, cancelHandler, allowCancel, parent);
        }
        #endregion

        #region Errors
        protected override void InvokeErrorsChanged(object sender, EventArgs eventArgs)
        {
            base.InvokeErrorsChanged(sender, eventArgs);
            //Пересылаем можно ли нажимать ok
            CheckIsOkEnabled();

        }


        protected override void AcceptButtonClicked()
        {
                OkClicked();
        }

        protected override void CancelButtonClicked()
        {
                CancelClicked();
        }


        protected override void TrySetInitialFocus()
        {

            if (ParentApplicationContainer != null)
                if (IsStandartOkCancelEnabled)
                {
                    if (IsOkVisible)
                    {
                         ParentApplicationContainer.okCancel.okButton.Focus();
                    }
                    else
                    {
                        if (AllowCancel)
                            ParentApplicationContainer.okCancel.cancelButton.Focus();
                    }
                }

            base.TrySetInitialFocus();
        }

        /// <summary>
        /// Этим определяем, что ok энейблится, когда все валидно, вызывается при смене первой ошибки в общей группе привязки
        /// </summary>
        internal void  CheckIsOkEnabled()
        {
            InvokeOkEnableChanged(IsValid);
        }

        public event BoolValueChangedHandler OkEnableChanged;
        /// <summary>
        /// Потомок вызывает, если хочет уведомить, что необходимо обновить Enable ok кнопки
        /// </summary>
        /// <param name="val"></param>
        protected void InvokeOkEnableChanged(bool val)
        {
            BoolValueChangedHandler changed = OkEnableChanged;
            if (changed != null) changed(val);
        }

        //Is Ok Visible
        public virtual bool IsOkVisible { get { return true; } }

        #endregion

        /// <summary>
        /// Что делать если нажали ok, как минимум делаем Invoke событию... multi  или Single data
        /// </summary>
        public /*abstract */ virtual void OkClicked(){throw new NotImplementedException("Необходимо переопределить OkClicked");}

        #region SingleData
        public bool IsDataSelectedHandling
        {
            get
            {
                return DataSelected != null;
            }

        }
        public event DataSelectedEventHandler DataSelected;
        protected void InvokeDataSelected(object data)
        {
            DataSelectedEventHandler selected = DataSelected;
            if (selected != null) selected(this, data);
        }

        protected void InvokeDataSelected()
        {
            InvokeDataSelected(null);
        } 
        #endregion
        #region MultiData
        public bool IsMultiDataSelectedHandling
        {
            get
            {
                return MultiDataSelected != null;
            }

        }
        public event MultiDataSelectedEventHandler MultiDataSelected;
        protected void InvokeMultiDataSelected(IEnumerable<object> data)
        {
            MultiDataSelectedEventHandler selected = MultiDataSelected;
            if (selected != null) selected(this, data);
        } 
        #endregion

        #region Cancel
        /// <summary>
        /// Потомок вызывает, когда хочет сказать, что нажали отмену и мы не возвращаем результата
        /// </summary>
        public event EventHandler CancelSelected;

        protected void InvokeCancelSelected()
        {
            EventHandler selected = CancelSelected;
            if (selected != null) selected(this, EventArgs.Empty);
        } 
        
        /// <summary>
        /// Что делать если нажали Cancel, кидаем событие CancelClicked
        /// </summary>
        public virtual void CancelClicked()
        {
            InvokeCancelSelected();
        }
        #endregion

        #region Customization

        /// <summary>
        /// The dialog, that is shown
        /// </summary>
        public DialogControl Current
        {
            get {
                if (ParentApplicationContainer != null)
                    return ParentApplicationContainer.Dialog;
                return null;
            }
        }

        /// <summary>
        /// is current dialog showing
        /// </summary>
        public bool IsCurrent
        {
            get { return this == Current; }
        }
        /// <summary>
        /// Передается из ShowDialog, но потомок может проигнорировать и при запросе вернуть свое значение
        /// </summary>
        public bool AllowCancel { get; set; } //решено, что диалог не вправе сам определять это. Вызывающий объект вправе решать, может ли диалог завершаться на Cancel

        /// <summary>
        /// Нужно ли для потомка показывать стандартные Ok и Cancel
        /// </summary>
        public /*abstract*/ virtual bool IsStandartOkCancelEnabled { get { throw new NotImplementedException("Необходимо переопределить IsStandartOkCancelEnabled"); } } 

        public virtual object OkContent
        {
            get { return "Принять"; }
        }

        public virtual object CancelContent
        {
            get { return "Отмена"; }
        }

        public virtual bool AutoSize { get { return false; } }
    

        #endregion
        
        /// <summary>
        /// Просто храним родителя
        /// </summary>
        public UIElement ParentWindow
        {
            get; set;
        }
    }
}